package com.zhouixi.repository;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class NodeRegistry {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private static final String NODE_PREFIX = "im:nodes:";

    private static final String NODE_OP_PREFIX = "im:node:ops:";
    // 节点存活时间（单位：毫秒）
    private static final long NODE_TTL = 300000L;

    // 节点存活时间（单位：秒）
    private static final long NODE__TTL = 30L;


    // 节点启动时调用，注册当前节点，解决集群中节点的唯一性问题
    @PostConstruct
    public void registerNode() {

    }

    public String getCurrentNodeId() {
        return System.getenv("nodeId");
    }

    public void registerNode(Long userId) {
        String nodeId = System.getenv("nodeId");
        redisTemplate.opsForHash().put(NODE_OP_PREFIX, userId, nodeId);
    }

    public String getOpNode(Long userId) {
        String nodeId = (String) redisTemplate.opsForHash().get(NODE_OP_PREFIX, userId);
        if (nodeId == null) {
            // 如果没有找到操作节点，可能是因为用户没有注册或节点过期
            throw new IllegalStateException("No operation node found for user: " + userId);
        }
        // 返回操作节点ID
        return nodeId;
    }

    public String getNodeForUser(String userId) {
        // 简单哈希取模（实际可用一致性哈希）
        int nodeCount = redisTemplate.keys(NODE_PREFIX + "*").size();
        int nodeIndex = Math.abs(userId.hashCode()) % nodeCount + 1;
        return "node-" + nodeIndex;
    }

    @PostConstruct
    public void startNodeHealthCheck() {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
            Set<String> nodeKeys = redisTemplate.keys(NODE_PREFIX + "*");
            if (nodeKeys == null) {
                return;
            }
            for (String key : nodeKeys) {
                // 检查节点是否过期（实际可通过心跳延长TTL）
                Long ttl = redisTemplate.getExpire(key);
                if (ttl == null || ttl < 0) {
                    redisTemplate.delete(key); // 清理过期节点
                }
            }
        }, 0, 10, TimeUnit.SECONDS); // 每10秒检测一次
    }

    // 节点定时心跳（延长存活时间）
    @Scheduled(fixedRate = 20000) // 每20秒发送一次心跳
    public void keepAlive() {
        String nodeId = System.getenv("nodeId");
        if (nodeId != null) {
            String key = NODE_PREFIX + nodeId;
            redisTemplate.expire(key, NODE__TTL, TimeUnit.SECONDS); // 延长TTL
        }
    }
}
